package com.croofr.test.junit.matcher;

import com.croofr.global.exceptions.CroofrException;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.internal.matchers.TypeSafeMatcher;

/**
 * Junit matchers (<a href="http://code.google.com/p/hamcrest/wiki/Tutorial">hamcrest</a>) for Exception.
 * <p/>
 * User: bednar<br/>
 * Date: Jan 24, 2010<br/>
 * Time: 10:26:15 PM
 *
 * @see org.hamcrest.BaseMatcher
 */
public final class ExceptionMatcher
{

    /**
     * Testing equals exception cause with cause as parameter.
     *
     * @param cause for testing with exception cause
     * @return CauseMatcher
     */
    public static Matcher<Exception> causeMatcher(String cause)
    {
        return new CauseMatcher(cause);
    }

    /**
     * Testing equals exception error key with error key as parameter.
     *
     * @param errorKey for testing with exception error key
     * @return ErrorKeyMatcher
     */
    public static Matcher<CroofrException> errorKeyMatcher(String errorKey)
    {
        return new ErrorKeyMatcher(errorKey);
    }

    private static class CauseMatcher extends TypeSafeMatcher<Exception>
    {

        private String message;

        private CauseMatcher(String message)
        {
            super();
            this.message = message;
        }

        @Override
        public boolean matchesSafely(Exception exception)
        {
            return message.equals(exception.getCause().toString());
        }

        @Override
        public void describeTo(Description description)
        {
            description.appendText("Exception with cause toString: '" + message + "'");
        }
    }

    private static class ErrorKeyMatcher extends TypeSafeMatcher<CroofrException>
    {
        private String errorKey;
        private CroofrException exception;

        private ErrorKeyMatcher(String errorKey)
        {
            this.errorKey = errorKey;
        }


        @Override
        public boolean matchesSafely(CroofrException exception)
        {
            this.exception = exception;

            return errorKey.equals(exception.getErrorKey());
        }

        @Override
        public void describeTo(Description description)
        {
            description.appendText(
                    "Expected " + CroofrException.class.getSimpleName() +
                            " with errorKey: '" + errorKey + "' but get: '" + exception.getErrorKey() + "'"
            );
        }
    }
}
